home *** CD-ROM | disk | FTP | other *** search
/ CD Ware Multimedia 1995 May / cd Ware (Juegos) Epimundo.iso / DOS / UT_SYSTM / CLOCK_RS.ZIP / IOCTL.C < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-20  |  16.7 KB  |  558 lines

  1. /*****************************************************************************/
  2. /*                THE FOLLOWING PROGRAM IS THE SOLE PROPERTY OF              */
  3. /*                               RONALD Q. SMITH                             */
  4. /*             CONTAINING HIS PROPRIETARY CONFIDENTIAL INFORMATION           */
  5. /*                       COPYRIGHT RONALD Q. SMITH 1992- 1994                */
  6. /*****************************************************************************/
  7.  
  8. /* Global data definitions                                                  */
  9.  
  10. #include <dos.h>
  11. #include <fcntl.h>
  12. #include <sys\types.h>
  13. #include <sys\stat.h>
  14. #include <io.h>
  15. #include <stdlib.h>
  16. #include <string.h>
  17. #include <ioctl.h>
  18.  
  19. /* Function prototypes                                                      */
  20.  
  21. static int ioctl_write(void * data, int length);
  22. static int ioctl_read(void * data, int length);
  23. static int open_clock(void);
  24.  
  25. /* Global static variables                                                  */
  26.  
  27. static unsigned int handle = 0;
  28. static unsigned char password[8] = "";
  29.  
  30. /*
  31. PROCEDURE: connec
  32.  
  33. connec changes the value of the CONNECTED flag in CLOCK.SYS.  Values supported
  34. are:
  35.     0   =   disconnected
  36.     1   =   connected for writes only (default)
  37.     2   =   connected for writes and periodic reads
  38.     3   =   connected for all operations
  39.  
  40. INTERFACE:
  41.         status = connec(&connected);
  42.  
  43.             "connected" is the new value of the connected flag.
  44.  
  45.             "status" is zero if the operation succeeds.  It is the DOS
  46.             error code if the operation fails.  Likely values are:
  47.                 1   =   Not CLOCK.SYS
  48.                 5   =   Incorrect password
  49.                 6   =   Unable to obtain handle for CLOCK$
  50.                 0xD =   Illegal value for connected
  51.                 -1  =   Internal error
  52.  
  53. */
  54.  
  55. extern int pascal far connec(int *connect)
  56. {
  57.         auto struct {
  58.             int function;
  59.             int connect;
  60.         } connect_data;
  61.         auto int status;
  62.  
  63. /* Copy data to be sent to local storage.                                   */
  64.  
  65.     connect_data.function = 1;          /* Set CONNECT  */
  66.     connect_data.connect = *connect;
  67.  
  68. /* Check for legal values.                                                  */
  69.  
  70.     if (connect_data.connect > 3)
  71.         return(0xD);
  72.  
  73. /* Write new value.                                                         */
  74.  
  75.      status = ioctl_write(&connect_data, sizeof connect_data);
  76.  
  77.     return ((status == sizeof connect_data) ? 0 : ((status < 0) ?
  78.         -status : -1));
  79.  
  80. }
  81.  
  82. /*
  83. PROCEDURE: stzone
  84.  
  85. stzone sets the time zone offsets and the time zone name.
  86.  
  87. INTERFACE:
  88.         status = stzone(&hour, &minute, &second, zone);
  89.  
  90.             "hour:minute:second" is the difference in time between UTC and
  91.             local time.  The values are positive West of Greenwich and
  92.             negative East.
  93.  
  94.             "zone" is a character string containing the local time zone name.
  95.             It must be LJSF (Left Justified, Space Filled) or LJNT (Left
  96.             Justified, NULL Terminated).  It must be no more than 32
  97.             characters in length.
  98.  
  99.             "status" is zero if the operation succeeds.  It is the DOS
  100.             error code if the operation fails.  Likely values are:
  101.                 1   =   Not CLOCK.SYS
  102.                 5   =   Incorrect password
  103.                 6   =   Unable to obtain handle for CLOCK$
  104.                 0xD =   Illegal value for offset
  105.                 -1  =   Internal error
  106. */
  107.  
  108. extern int pascal far stzone(int *std_hour, int *std_minute, int *std_second,
  109.     unsigned char std_name[32], int *day_hour, int *day_minute,
  110.     int *day_second, unsigned char day_name[32])
  111.  
  112. {
  113.     auto struct {
  114.         int function;
  115.         struct time_zone standard;
  116.         struct time_zone daylight;
  117.     } zone_data;
  118.     auto int status;
  119.  
  120. /* Copy values to local storage.  LJSF zones.                               */
  121.  
  122.     zone_data.function = 2;
  123.  
  124.     zone_data.standard.offs.hour = *std_hour;
  125.     zone_data.standard.offs.minute = *std_minute;
  126.     zone_data.standard.offs.second = *std_second;
  127.     memcpy(zone_data.standard.zone, std_name, sizeof zone_data.standard.zone);
  128.  
  129.     zone_data.daylight.offs.hour = *day_hour;
  130.     zone_data.daylight.offs.minute = *day_minute;
  131.     zone_data.daylight.offs.second = *day_second;
  132.     memcpy(zone_data.daylight.zone, day_name, sizeof zone_data.daylight.zone);
  133.  
  134. /* Check for legal offset values.                                           */
  135.  
  136.     if ((abs(zone_data.standard.offs.hour) > 23) ||
  137.         (abs(zone_data.standard.offs.minute) > 59) ||
  138.         (abs(zone_data.standard.offs.second) > 59) ||
  139.         (abs(zone_data.daylight.offs.hour) > 23) ||
  140.         (abs(zone_data.daylight.offs.minute) > 59) ||
  141.         (abs(zone_data.daylight.offs.second) > 59))
  142.     {
  143.         return(0xD);
  144.     }
  145.  
  146. /* Write new values to CLOCK.SYS                                            */
  147.  
  148.     status = ioctl_write(&zone_data, sizeof zone_data);
  149.  
  150.     return ((status == sizeof zone_data) ? 0 : ((status < 0) ?
  151.         -status : -1));
  152.  
  153. }
  154.  
  155. /*
  156. PROCEDURE: stmode
  157.  
  158. stmode sets a new value for the mode flag.
  159.  
  160. INTERFACE:
  161.         status = stmode(&mode);
  162.  
  163.             "mode" is the new value for the mode flag.  The "mode" flag
  164.             contains a set of bits which may be set in any combination.
  165.  
  166.             "status" is zero if the operation succeeds.  It is the DOS
  167.             error code if the operation fails.  Likely values are:
  168.                 1   =   Not CLOCK.SYS
  169.                 5   =   Incorrect password
  170.                 6   =   Unable to obtain handle for CLOCK$
  171.                 0xD =   Illegal value for mode
  172.                 -1  =   Internal error
  173. */
  174.  
  175. extern int pascal far stmode(struct modes *mode)
  176.  
  177. {
  178.     auto struct {
  179.         int function;
  180.         struct modes mode;
  181.     } mode_data;
  182.     auto int status;
  183.  
  184. /* Copy values to local storage.                                            */
  185.  
  186.     mode_data.function = 3;
  187.     mode_data.mode = *mode;
  188.  
  189. /* Write new value to CLOCK.SYS                                             */
  190.  
  191.     status = ioctl_write(&mode_data, sizeof mode_data);
  192.  
  193.     return ((status == sizeof mode_data) ? 0 : ((status < 0) ?
  194.         -status : -1));
  195.  
  196. }
  197.  
  198. /*
  199. PROCEDURE: rstrct
  200.  
  201. rstrct sets the time restriction limit values.
  202.  
  203. INTERFACE:
  204.         status = rstrct(&back_hour, &back_minute, &back_second, &forward_hour,
  205.             &forward_minute, &forward_second);
  206.  
  207.             "back_hour:back_minute:back_second" is the new limit on backward
  208.             time changes.  All values must be positive and less than or
  209.             equal to 23:59:59.
  210.  
  211.             "forward_hour:forward_minute:forward_second" is the new limit on
  212.             forward time changes.  All values must be positive and less than
  213.             or equal to 23:59:59.
  214.  
  215.             "status" is zero if the operation succeeds.  It is the DOS
  216.             error code if the operation fails.  Likely values are:
  217.                 1   =   Not CLOCK.SYS
  218.                 5   =   Incorrect password
  219.                 6   =   Unable to obtain handle for CLOCK$
  220.                 0xD =   Illegal value for limits
  221.                 -1  =   Internal error
  222. */
  223.  
  224. extern int pascal far rstrct(int *back_hour, int *back_minute,
  225.     int *back_second, int *forward_hour, int *forward_minute,
  226.     int *forward_second)
  227.  
  228. {
  229.     auto struct {
  230.         int function;
  231.         int back_hour;
  232.         int back_minute;
  233.         int back_second;
  234.         int forward_hour;
  235.         int forward_minute;
  236.         int forward_second;
  237.     } rstrct_data;
  238.     auto int status;
  239.  
  240. /* Copy values to local storage.                                            */
  241.  
  242.     rstrct_data.function = 4;
  243.     rstrct_data.back_hour = *back_hour;
  244.     rstrct_data.back_minute = *back_minute;
  245.     rstrct_data.back_second = *back_second;
  246.     rstrct_data.forward_hour = *forward_hour;
  247.     rstrct_data.forward_minute = *forward_minute;
  248.     rstrct_data.forward_second = *forward_second;
  249.  
  250. /* Check values for legal limits.                                           */
  251.  
  252.     if ((rstrct_data.back_hour < 0) || (rstrct_data.back_hour > 23) ||
  253.         (rstrct_data.back_minute < 0) || (rstrct_data.back_minute > 59) ||
  254.         (rstrct_data.back_second < 0) || (rstrct_data.back_second > 59) ||
  255.         (rstrct_data.forward_hour < 0) || (rstrct_data.forward_hour > 23) ||
  256.         (rstrct_data.forward_minute < 0) || (rstrct_data.forward_minute > 59)
  257.         || (rstrct_data.forward_second < 0) ||
  258.         (rstrct_data.forward_second > 59))
  259.     {
  260.         return(0xD);
  261.     }
  262.  
  263. /* Write new values to CLOCK.SYS                                            */
  264.  
  265.     status = ioctl_write(&rstrct_data, sizeof rstrct_data);
  266.  
  267.     return ((status == sizeof rstrct_data) ? 0 : ((status < 0) ?
  268.         -status : -1));
  269.  
  270. }
  271.  
  272. /*
  273. PROCEDURE: tdisp
  274.  
  275. tdisp sets the time display cursor location.  The mode to enable the display
  276. must be set separately with stmode.
  277.  
  278. INTERFACE:
  279.         status = tdisp(&disp_x, &disp_y, &attribute);
  280.  
  281.             "disp_x" is the screen x coordinate in character positions of
  282.             the left-most character of the time display.  The value must be
  283.             positive and less than 256.
  284.  
  285.             "disp_y" is the screen y coordinate in lines of the time display.
  286.             The value must be positive and less than 256.
  287.  
  288.             "attribute" is the screen attribute to be used for the display.
  289.             The value must be less than 256 and the low-order three bits of
  290.             each nybble must not be equal.
  291.  
  292.             "status" is zero if the operation succeeds.  It is the DOS
  293.             error code if the operation fails.  Likely values are:
  294.                 1   =   Not CLOCK.SYS
  295.                 5   =   Incorrect password
  296.                 6   =   Unable to obtain handle for CLOCK$
  297.                 0xD =   Illegal value for tdisp
  298.                 -1  =   Internal error
  299. */
  300. extern int pascal far tdisp(int *disp_x, int *disp_y, int *attribute)
  301.  
  302. {
  303.  
  304.     auto struct {
  305.         int function;
  306.         int disp_x;
  307.         int disp_y;
  308.         int attribute;
  309.     } tdisp_data;
  310.     auto int status;
  311.  
  312. /* Copy values to local storage.                                            */
  313.  
  314.     tdisp_data.function = 5;
  315.     tdisp_data.disp_x = *disp_x;
  316.     tdisp_data.disp_y = *disp_y;
  317.     tdisp_data.attribute = *attribute;
  318.  
  319. /* Check values for ranges.                                                 */
  320.  
  321.     if ((tdisp_data.disp_x < 0) || (tdisp_data.disp_x > 255) ||
  322.         (tdisp_data.disp_y < 0) || (tdisp_data.disp_y > 255) ||
  323.         (tdisp_data.attribute < 0) || (tdisp_data.attribute > 255) ||
  324.         ((tdisp_data.attribute & 7) == ((tdisp_data.attribute >> 4) & 7)))
  325.     {
  326.         return(0xD);
  327.     }
  328.  
  329. /* Write new values to CLOCK.SYS                                            */
  330.  
  331.     status = ioctl_write(&tdisp_data, sizeof tdisp_data);
  332.  
  333.     return ((status == sizeof tdisp_data) ? 0 : ((status < 0) ?
  334.         -status : -1));
  335.  
  336. }
  337.  
  338. /*
  339. PROCEDURE: setpw
  340.  
  341. setpw sets the password to be used on all future operations to change the
  342. CLOCK.SYS values.  setpw must be called with the correct password prior to
  343. any operation after password checking is enabled.  If password checking is
  344. not enabled, setpw is not required.
  345.  
  346. INTERFACE:
  347.  
  348.         setpw(pword);
  349.  
  350.             "pword" is an 8-character array containing the password to
  351.             be used.  It must be LJSF or LJNF (Left Justified, NULL Filled).
  352.  
  353. */
  354.  
  355. extern void pascal far setpw(unsigned char *pword)
  356.  
  357. {
  358.  
  359. /* Copy the password to local storage for use on later calls.               */
  360.  
  361.     memcpy(password, pword, sizeof password);
  362.  
  363. }
  364.  
  365. /*
  366. PROCEDURE: newpw
  367.  
  368. newpw sets a new password into CLOCK.SYS.  This new password is immediately
  369. effective.  newpw also copies the new password to local storage as the current
  370. password if the operation of setting it in CLOCK.SYS is successful.
  371.  
  372. INTERFACE:
  373.  
  374.         status = newpw(pword);
  375.  
  376.             "pword" is the new password.  It must be exactly 8 characters in
  377.             length.  It may be LJSF or LJNF.
  378.  
  379.             "status" is zero if the operation succeeds.  It is the DOS
  380.             error code if the operation fails.  Likely values are:
  381.                 1   =   Not CLOCK.SYS
  382.                 5   =   Incorrect password
  383.                 6   =   Unable to obtain handle for CLOCK$
  384.                 -1  =   Internal error
  385. */
  386.  
  387. extern int pascal far newpw(unsigned char *pword)
  388.  
  389. {
  390.  
  391.     auto struct {
  392.         int function;
  393.         unsigned char pword[sizeof password];
  394.     } newpw_data;
  395.     auto int status;
  396.  
  397. /* Copy the values to local storage.                                        */
  398.  
  399.     newpw_data.function = 6;
  400.     memcpy(newpw_data.pword, pword, sizeof password);
  401.  
  402. /* Set the new password in CLOCK.SYS                                        */
  403.  
  404.     status = ioctl_write(&newpw_data, sizeof newpw_data);
  405.  
  406. /* If everything OK, copy the new password to the current password.         */
  407.  
  408.     if (status == sizeof newpw_data)
  409.     {
  410.         memcpy(password, pword, sizeof password);
  411.         return(0);
  412.     }
  413.  
  414.     return ((status < 0) ? -status : -1);
  415.  
  416. }
  417.  
  418.  
  419. /*
  420. PROCEDURE: clksta
  421.  
  422. clksta gets the current state of CLOCK.SYS.
  423.  
  424. INTERFACE:
  425.         status = clksta(&data);
  426.  
  427.         "data" is a structure that will contain the returned information.
  428.  
  429.         "status" is the number of bytes read or the negative of the DOS
  430.         error status if an error occurs.
  431.  
  432. */
  433.  
  434. extern int pascal far clksta(struct CLOCK_DATA *data)
  435.  
  436. {
  437.  
  438.     return(ioctl_read(data, sizeof (struct CLOCK_DATA)));
  439.  
  440. }
  441.  
  442. /****************************************************************************/
  443. /*                       INTERNAL FUNCTIONS                                 */
  444. /****************************************************************************/
  445.  
  446. /*
  447. PROCEDURE: ioctl_write
  448.  
  449. ioctl_write performs a "Send Control Data to Character Device" function.
  450.  
  451. INTERFACE:
  452.     status = ioctl_write(data, length);
  453.  
  454.         "data" is an array of "length" bytes.
  455.  
  456.         "length" is the number of bytes to be sent.
  457.  
  458.         "status" is the number of bytes accepted by the device or the negative
  459.         of _doserrno if an error occurs.
  460.  
  461. */
  462.  
  463. static int ioctl_write(void * data, int length)
  464.  
  465. {
  466.         auto union REGS regs;
  467.         auto unsigned char send_data[200];  /* Leave room for growth    */
  468.  
  469. /* If file for CLOCK$ not open, open it.                                    */
  470.  
  471.     if (!handle)
  472.     {
  473.         if (open_clock() <= 0)
  474.             return(-_doserrno);
  475.     }
  476.  
  477. /* Copy password and caller's data to same area to send.                    */
  478.  
  479.     memcpy(send_data, password, sizeof password);
  480.     memcpy(&send_data[sizeof password], data, length);
  481.  
  482.     regs.x.ax = 0x4403;             /* IOCTL Send Control Data  */
  483.     regs.x.bx = handle;
  484.     regs.x.cx = length + sizeof password;
  485.     regs.x.dx = (int) send_data;    /* Send data bytes  */
  486.  
  487.     intdos(®s, ®s);
  488.  
  489.     return(regs.x.cflag ? -_doserrno : regs.x.ax - sizeof password);
  490. }
  491.  
  492.  
  493. /*
  494. PROCEDURE: ioctl_read
  495.  
  496. ioctl_read performs a "Read Control Data from Character Device" function.
  497.  
  498. INTERFACE:
  499.     status = ioctl_read(data, length);
  500.  
  501.         "data" is an array of "length" bytes to receive the information.
  502.  
  503.         "length" is the number of bytes to be read.
  504.  
  505.         "status" is the number of bytes returned by the device or
  506.         is the negative of the DOS error status if an error occurs.
  507.  
  508. */
  509.  
  510. static int ioctl_read(void * data, int length)
  511.  
  512. {
  513.         auto union REGS regs;
  514.  
  515. /* If file for CLOCK$ not open, open it.                                    */
  516.  
  517.     if (!handle)
  518.     {
  519.         if (open_clock() <= 0)
  520.             return(-_doserrno);
  521.     }
  522.  
  523.     regs.x.ax = 0x4402;             /* IOCTL Read Control Data  */
  524.     regs.x.bx = handle;
  525.     regs.x.cx = length;
  526.     regs.x.dx = (int) data;         /* Read data bytes  */
  527.  
  528.     intdos(®s, ®s);
  529.  
  530.     return(regs.x.cflag ? -_doserrno : regs.x.ax);
  531.  
  532. }
  533.  
  534. /*
  535. PROCEDURE: open_clock
  536.  
  537. "open_clock" opens a file handle for the CLOCK$ device.
  538.  
  539. INTERFACE:
  540.         open_clock();
  541.  
  542.                    open_clock returns the file handle or the value -1 if
  543.                    unable to establish a handle.
  544. */
  545.  
  546. static int open_clock(void)
  547.  
  548. {
  549.         return(handle = open("CLOCK$",O_RDWR));
  550. }
  551.  
  552. /*****************************************************************************/
  553. /*                THE PRECEDING PROGRAM IS THE SOLE PROPERTY OF              */
  554. /*                               RONALD Q. SMITH                             */
  555. /*             CONTAINING HIS PROPRIETARY CONFIDENTIAL INFORMATION           */
  556. /*                       COPYRIGHT RONALD Q. SMITH 1992 - 1994               */
  557. /*****************************************************************************/
  558.